package main

import (
	"encoding/json"
	"fmt"
	"log"
	"monitor/RequestLimit"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"sync"
	"time"
)

// string 接口名
// 数量
var labels map[string]map[string]int64
var ipAccess map[string]int64
var labels1 *sync.Map
var ipAccess1 *sync.Map
var limitation int64
var ch chan router
var wg sync.WaitGroup

func InitData() {
	ch = make(chan router)
	limitation = 50
	ipAccess = make(map[string]int64)
	labels = make(map[string]map[string]int64)
}

type router struct {
	Ip    string
	Path  string
	Mutex *sync.RWMutex
	Types bool
}

type Msg struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			logFile, _ := os.OpenFile("./error.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
			log.SetOutput(logFile)
			log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
			log.SetPrefix("[Ares]")
			log.Panicf("Recovered in f%v\n", r)
			fmt.Printf("Recovered in f%v\n", r)
		}
	}()
	InitData()
	go cron()
	go chanCl()
	proxy := httputil.NewSingleHostReverseProxy(&url.URL{
		//Scheme: "https",
		Scheme: "http",
		//Host: "api.aruisigame.com",
		//Host: "192.168.1.6:8080",
		//Host: "localhost:9090",
		Host: "localhost:3212",
	})
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if len(r.URL.Path) < 6 {
			cors(w)
			re := Success(606, "错误", r.URL.Path)
			w.Write(re)
			return
		}
		if r.URL.Path[:5] != "/api/" {
			cors(w)
			re := Success(606, "错误")
			w.Write(re)
			return
		}
		r.URL.Path = r.URL.Path[5:]
		if r.Method == "GET" {
			proxy.ServeHTTP(w, r)
			return
		}
		switch r.URL.Path {
		case "termui": // 统计
			// 统计流量
			//QPSstatic.Counter.Increase()
			fmt.Println(labels)
			//io.WriteString(w, Success(201, "ok", labels))
			break
		case "login": // 登录
			proxy.ServeHTTP(w, r)
			break
		case "code_login": // 验证码登录
			proxy.ServeHTTP(w, r)
			break
		case "send_code": // 发送验证码
			proxy.ServeHTTP(w, r)
			break
		case "register": // 注册
			proxy.ServeHTTP(w, r)
			break
		case "ws": // socket
			proxy.ServeHTTP(w, r)
			break
		case "CallbackPay":
			proxy.ServeHTTP(w, r)
			break
		default:
			ip := RequestLimit.IpGet(r)
			routers := router{Ip: ip, Path: r.URL.Path, Types: true}
			routers.Mutex = new(sync.RWMutex)
			ch <- routers
			routers.Mutex.RLock()
			defer routers.Mutex.RUnlock()
			fmt.Println(ip, r.URL.Path, labels[ip], ipAccess[ip])
			if ipAccess[ip] >= limitation {
				cors(w)
				re := Success(201, "客官慢点...")
				fmt.Println(string(re))
				w.Write(re)
			} else {
				proxy.ServeHTTP(w, r) // 代理
			}
		}
	})
	log.Fatal(http.ListenAndServe(":3211", nil))
	//log.Fatal(http.ListenAndServe(":9091", nil))
}

// Success 成功回调
func Success(code int, msg string, data ...interface{}) []byte {
	json2, _ := json.Marshal(
		Msg{
			Code: code,
			Msg:  msg,
			Data: data,
		})
	return json2
}

func cors(w http.ResponseWriter) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
	w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
	w.Header().Set("Access-Control-Allow-Credentials", "true")
	w.WriteHeader(http.StatusOK)
}

func mapCount(ip, path string, types bool) {
	defer wg.Done()
	if types {
		if labels[ip] == nil {
			labels[ip] = make(map[string]int64)
		}
		labels[ip][path]++
		ipAccess[ip]++
	} else {
		labels = make(map[string]map[string]int64)
		ipAccess = make(map[string]int64)
	}
}

func cron() {
	for {
		select {
		case times := <-time.After(time.Minute * 1):
			fmt.Println(times, "清空访问次数")
			routers := router{Types: false}
			routers.Mutex = new(sync.RWMutex)
			ch <- routers
		}
	}
}

func chanCl() {
	for {
		select {
		case conn := <-ch:
			conn.Mutex.Lock()
			wg.Add(1)
			mapCount(conn.Ip, conn.Path, conn.Types)
			wg.Wait()
			conn.Mutex.Unlock()
			break
		}
	}

}
